package gsde.springboot.eurekaserver;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.client.RestTemplate;

import java.util.*;
import java.util.concurrent.*;

class MyTask implements Runnable
{
    public GsdeServiceHeartBeatManage beatManage = null;

    public boolean stop = false;
    protected HashMap<String, Object> map = new HashMap<>();

    public MyTask(String servicehost, int port, String servicename)
    {
        map.put("SERVICE_HOST", servicehost);
        map.put("PORT", port);
        map.put("SERVICE_NAME", servicehost);

        //String runMsg = (String) map.get("SERVICE_RUN_MSG");
      //  long starttime = (long) map.get("SERVICE_START_TIME");
        map.put("SERVICE_START_TIME", System.currentTimeMillis());
    }
    @Override
    public void run()
    {
        if (stop == true)
        {
            return;
        }

        System.out.println(map);
        beatManage.putServiceStatus(map);
    }
}


public class GsdeServiceHeartBeatManage {
    protected final ConcurrentHashMap<String, GsdeServiceProperty> __recentlyStatus = new ConcurrentHashMap<>();
    protected final long __aliveTimeSpace = 20* 1000; //2 分钟

    protected final ConcurrentHashMap<String, Object> __serviceAliveMap = new ConcurrentHashMap<>();
    public GsdeServiceHeartBeatManage()
    {

    }

    /**
     * 添加进程运行信息
     *  map: SERVICE_HOST:主机IP， PORT：端口 ，SERVICE_NAME：服务名
     *       SERVICE_RUN_MSG ：运行信息  SERVICE_START_TIME：开始时间, 开始时间减去现在时间，极为运行时常
     * @param map
     */
    public synchronized void putServiceStatus(Map<String, Object> map)
    {
        // 服务进程标志
        //String processuuid = (String) map.get("PROCESS_UUID");
        String hostip = (String) map.get("SERVICE_HOST");
        int port = (int) map.get("PORT");
        String serviceName =  (String) map.get("SERVICE_NAME");
        String runMsg = (String) map.get("SERVICE_RUN_MSG");
        long starttime = (long) map.get("SERVICE_START_TIME");

        String  processuuid = hostip + ":" + String.valueOf(port) + ":" + serviceName;

        long curtime = System.currentTimeMillis();
        System.out.println(curtime);

        GsdeServiceProperty recentlyProperty= this.__recentlyStatus.get(processuuid);

        long lastRecentlyUpdateTime = 0;

        boolean recentlyPropertyExists = false;
        //最新收到的
        if (recentlyProperty == null)
        {
            recentlyProperty = new GsdeServiceProperty(hostip, port, serviceName);
            recentlyProperty.setStartTime(starttime);
            this.__recentlyStatus.put(processuuid, recentlyProperty);
        }

        recentlyProperty.setUpdateTime(curtime + __aliveTimeSpace);
        recentlyProperty.setServiceRunMsg(runMsg);
    }

    public synchronized boolean isAliveStatus(HashMap<String, Object> map)
    {
        long curTime = System.currentTimeMillis();

        String hostip = (String) map.get("SERVICE_HOST");
        int port = (int) map.get("PORT");
        String serviceName =  (String) map.get("SERVICE_NAME");

        String  processuuid = hostip + ":" + String.valueOf(port) + ":" + serviceName;

        GsdeServiceProperty serviceProperty = null;

        serviceProperty= (GsdeServiceProperty) this.__recentlyStatus.get(processuuid);

        //如果服务进程只发送一次更新消息，状态为活着 ： 1

        System.out.println("curtime - updaetime : " +String.valueOf(curTime
                - serviceProperty.getUpdateTime()));

        if ( curTime - serviceProperty.getUpdateTime() > __aliveTimeSpace * 2 )
        {
            return false;
        }

        return true;

    }

    public synchronized boolean isAliveStatus(String processuuid)
    {
        long curTime = System.currentTimeMillis();

        GsdeServiceProperty serviceProperty = null;

        serviceProperty= (GsdeServiceProperty) this.__recentlyStatus.get(processuuid);

        //如果服务进程只发送一次更新消息，状态为活着 ： 1

        System.out.println("curtime - updaetime : " +String.valueOf(curTime
                - serviceProperty.getUpdateTime()));

        System.out.println("run time  ： " + String.valueOf(serviceProperty.getRunTime()));

        if ( curTime - serviceProperty.getUpdateTime() > __aliveTimeSpace * 2 )
        {
            return false;
        }

        return true;

    }

    public synchronized  void checkHeartbeat()
    { Set<String> set = this.__recentlyStatus.keySet();
        long receivetimes = 0;

        GsdeServiceProperty serviceProperty = null;
        long curTime = System.currentTimeMillis();

        for (String key : set)
        {
             System.out.print(key  + " : "+ String.valueOf(isAliveStatus(key)));
        }

    }
    public synchronized boolean updateAliveStatus(HashMap<String, Object> map)
    {
        Set<String> set = this.__recentlyStatus.keySet();
        long receivetimes = 0;

        GsdeServiceProperty serviceProperty = null;
        long curTime = System.currentTimeMillis();

        for (String key : set)
        {
            serviceProperty= (GsdeServiceProperty) this.__recentlyStatus.get(key);

            //如果服务进程只发送一次更新消息，状态为活着 ： 1

            if (serviceProperty.getUpdateTime() - curTime <__aliveTimeSpace / 4)
            {
                __serviceAliveMap.put(key, 0);
                continue;
            }
            else {
                __serviceAliveMap.put(key, 1);
            }
        }

        // 获得更新次数
        return false;
    }


    public static void main(String[] args) {

        Map<String,Object> data = new HashMap<>();
        /**
         * 小伙伴发现没有，地址居然是http://service-provider
         * 居然不是http://127.0.0.1:8082/
         * 因为他向注册中心注册了服务，服务名称service-provider,我们访问service-provider即可
         */
        RestTemplate restTemplate = new RestTemplate();


        HttpHeaders headers = new HttpHeaders();

        headers.setContentType(MediaType.MULTIPART_FORM_DATA);

        headers.setContentType(MediaType.APPLICATION_JSON);//设置参数类型和编码

        HashMap<String, Object> map = new HashMap<>();

        map.put("SERVICE_HOST", "192.1.2.46");
        map.put("PORT", 8088);
        map.put("SERVICE_NAME", "jisuanserivce");

        Map<String, Object> map1 = new HashMap<>();
        map1.put("name", "myname");

        map1.put("city", "CHSH000000" );

        GsdeHttpService service = new GsdeHttpService();

        Object obj = service.postHttp("http://127.0.0.1:8000/list", map1);
      //  HttpEntity<Map<String,Object>> request = new HttpEntity<>(map, headers);//包装到HttpEntity
      //  data = restTemplate.getForObject("http://127.0.0.1:8000/list",
             //   Map.class, map1);

     //   LinkedBlockingQueue
     //   ScheduledExecutorService

        MyTask myTask1 = new MyTask("192.1.2.46", 8088, "calcprocess");
        GsdeServiceHeartBeatManage beatManage = new GsdeServiceHeartBeatManage();

        myTask1.beatManage = beatManage;
//
        ScheduledExecutorService executor =  Executors.newScheduledThreadPool(5);
        System.out.println(executor.getClass().toString());
       executor.scheduleWithFixedDelay(
             myTask1,
                0,
                10 * 1000,
                TimeUnit.MILLISECONDS);


        MyTask myTask2 = new MyTask("192.1.2.46", 8089, "calcprocess1");
        executor.scheduleWithFixedDelay(
                myTask2,
                2000,
                10 * 1000,
                TimeUnit.MILLISECONDS);
        myTask2.beatManage = beatManage;



        try {
        //    timer.scheduleAtFixedRate(myTask1, 0, 60 * 1000);
        } catch (Exception e) {

        }

        int n = 0;



        while (true)
        {
            try{
                Thread.sleep(20000);
            }
            catch (Exception e)
            {

            }
            beatManage.checkHeartbeat();
          //  System.out.println(beatManage.isAliveStatus(map));
            n++;
            if (n >= 15)
            {
               myTask1.stop = true;
        }

            if (n >= 30)
            {
               break;
            }


        }
    }
}
